﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using XTF_快速设备管理器.Properties;

namespace XTF_快速设备管理器
{
    internal class Program
    {

        static FileInfo devcon64 = null;
        static readonly string workPath = Environment.CurrentDirectory;
        static bool isDebug = false;
        static Dictionary<int, MyStatus> myStatus = new Dictionary<int, MyStatus>();
        //static MyInfo myInfo = new MyInfo();

        static void Main(string[] args)
        {
            myStatus = new Dictionary<int, MyStatus>()
            {
                {0x01,new MyStatus("启用","Enable")},
                {0x02,new MyStatus("禁用","Disable")},
                {0x03,new MyStatus("重启","Restart")},
            };

            devcon64 = new FileInfo(Path.Combine(workPath, "devcon64.exe"));
            if (!devcon64.Exists)
            {
                string tempPath = Environment.GetEnvironmentVariable("Temp");
                devcon64 = new FileInfo(Path.Combine(tempPath, devcon64.Name));
                File.WriteAllBytes(devcon64.FullName, Resources.devcon64);
            }
            int g_status = MyInfo.Zero;
            if (args.Length > 0)
            {
                for (int i = 0; i < args.Length; i++)
                {
                    switch (args[i].Trim().ToLower())
                    {
                        case "/enable":
                            g_status = MyInfo.Enable;
                            break;
                        case "/启用":
                            g_status = MyInfo.Enable;
                            break;
                        case "/disable":
                            g_status = MyInfo.Disable;
                            break;
                        case "/禁用":
                            g_status = MyInfo.Disable;
                            break;
                        case "/restart":
                            g_status = MyInfo.Restart;
                            break;
                        case "/重启":
                            g_status = MyInfo.Restart;
                            break;
                        case "/debug":
                            isDebug = true;
                            break;
                        default:
                            break;
                    }
                }
                string arg = string.Join(" ", args);
                if (g_status == MyInfo.Zero && !isDebug)
                {
                    List<string> res = Run(devcon64, arg);
                    res.ForEach(str => Console.WriteLine(str.ToString()));
                    return;
                }
            }
            string baseBoard = GetBaseBoardInfo();
            SetDevStatus(baseBoard, g_status);
        }

        private static void SetDevStatus(string baseBoard, int g_status = 0)
        {
            try
            {
                Console.WriteLine($"[{baseBoard}] - 开始设置设备状态...\r\n");
                Dictionary<string, int> myCount = new Dictionary<string, int>()
                {
                    {"enable",0 },{"disable",0 },{"restart",0 }
                };
                List<DevInfo> devInfos = GetDevInfos(workPath);
                foreach (var devInfo in devInfos)
                {
                    if (devInfo.Name == "*" || baseBoard.ToLower().Contains(devInfo.Name.ToLower()))
                    {
                        if (g_status > MyInfo.Zero)
                            devInfo.Status = g_status;
                        string statusNmae = myStatus[devInfo.Status].Name;
                        string statusValue = myStatus[devInfo.Status].Value;
                        string devClass= devInfo.Class.StartsWith("@") ? devInfo.Class : $"@{devInfo.Class}";
                        string args = $"{statusValue} \"{devClass}\"";
                        if (devInfo.Status > MyInfo.Zero)
                        {
                            Console.WriteLine($"{devInfo.Type}: {statusNmae} => {devInfo.Class}");
                            List<string> res = Run(devcon64, args);
                            res.ForEach(str =>
                            {
                                if (isDebug)
                                {
                                    Console.WriteLine(str);
                                }
                                else
                                {
                                    if (!str.ToLower().Contains(devInfo.Class.ToLower()))
                                    {
                                        Console.WriteLine(str);
                                    }
                                }
                            });
                            switch (devInfo.Status)
                            {
                                case MyInfo.Enable:
                                    myCount["enable"]++;
                                    break;
                                case MyInfo.Disable:
                                    myCount["disable"]++;
                                    break;
                                case MyInfo.Restart:
                                    myCount["restart"]++;
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
                Console.WriteLine();
                Console.WriteLine($"已启用: {myCount["enable"]} devices, 已禁用: {myCount["disable"]} devices, " +
                    $"已重启: {myCount["restart"]} devices");
                Console.WriteLine();
                if (isDebug)
                {
                    TimeExit(10000);
                }
                else
                {
                    TimeExit(100);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        private static List<string> Run(FileInfo fileInfo, string args, string workPath = default)
        {
            workPath = workPath ?? Environment.CurrentDirectory;
            string fileName = fileInfo.DirectoryName == workPath ? fileInfo.Name : fileInfo.FullName;
            Process p = new Process
            {
                StartInfo = new ProcessStartInfo()
                {
                    FileName = Environment.GetEnvironmentVariable("ComSpec"),
                    Arguments = $"/C {fileName} {args}",
                    WorkingDirectory = workPath,
                    CreateNoWindow = true,
                    UseShellExecute = false,
                    RedirectStandardInput = true,
                    RedirectStandardOutput = true,
                }
            };
            if (isDebug)
            {
                Console.WriteLine($"cmdline: {p.StartInfo.Arguments.Substring(3)}");
            }
            List<string> outLines = new List<string>();
            if (p.Start())
            {
                while (!p.StandardOutput.EndOfStream)
                {
                    outLines.Add(p.StandardOutput.ReadLine());
                }
            }
            return outLines;
        }

        private static List<DevInfo> GetDevInfos(string workPath)
        {
            FileInfo fi = new FileInfo(Path.Combine(workPath, "DevList.dev"));
            List<DevInfo> devInfos = new List<DevInfo>();
            if (fi.Exists)
            {
                string[] fileInfos = File.ReadAllLines(fi.FullName);
                foreach (string info in fileInfos)
                {
                    if (string.IsNullOrEmpty(info.Trim()) || info.Trim().StartsWith("#"))
                        continue;
                    string[] infos = info.Split('|');
                    if (infos.Length == 4)
                    {
                        int status = 0;
                        foreach (var item in myStatus)
                        {
                            if (item.Value.Name.Equals(infos[3].Trim()))
                            {
                                status = item.Key;
                                break;
                            }
                            if (item.Value.Value.Equals(infos[3].Trim(), StringComparison.CurrentCultureIgnoreCase))
                            {
                                status = item.Key;
                                break;
                            }
                        }
                        DevInfo devInfo = new DevInfo()
                        {
                            Name = infos[0],
                            Type = infos[1],
                            Class = infos[2],
                            Status = status,
                        };
                        devInfos.Add(devInfo);
                    }
                }
            }
            else
            {
                List<string> help = new List<string>()
                {
                    "#使用方法:",
                    "#查询PCI设备Class：DevQuickManage.exe find pci\\*",
                    "#全局设置设备状态：DevQuickManage.exe /[enable|启用|disable|禁用]",
                    "#设备列表格式:",
                    "#主板型号|设备类型|设备Class|状态[enable|启用|disable|禁用]",
                    "#禁用板载声卡：",
                    "#B460M-PLUS|板载声卡|PCI\\VEN_10DE&DEV_10F1&SUBSYS_00007377&REV_A1|disable",
                    "#重启板载声卡：",
                    "#B460M-PLUS|板载声卡|PCI\\VEN_10DE&DEV_10F1&SUBSYS_00007377&REV_A1|restart",
                    "",
                };
                File.WriteAllLines(fi.FullName, help);
            }
            return devInfos;
        }

        private static string GetBaseBoardInfo()
        {
            string product = null;
            var moc = new ManagementClass("Win32_BaseBoard").GetInstances();
            foreach (ManagementObject mo in moc.Cast<ManagementObject>())
            {
                try
                {
                    product = (string)mo["Product"];
                }
                catch (Exception)
                {
                }
            }
            return product;
        }

        private static void TimeExit(int time)
        {
            float s = time / 1000;
            for (int i = 0; i < s; i++)
            {
                Console.WriteLine($"此窗口在{s - i}秒后自动退出...");
                Console.CursorTop--;
                //Console.CursorLeft = 0;
                Thread.Sleep(1000);
            }
        }
    }

    /// <summary>
    /// 设备列表类
    /// </summary>
    class DevInfo
    {
        public string Name { get; set; }
        public string Type { get; set; }
        public string Class { get; set; }
        public int Status { get; set; }
        public DevInfo() { }
    }
    class MyStatus
    {
        public string Name { get; set; }
        public string Value { get; set; }
        public MyStatus(string name, string value)
        {
            Name = name;
            Value = value;
        }
    }

    static class MyInfo
    {
        public const int Zero = 0x00;
        public const int Enable = 0x01;
        public const int Disable = 0x02;
        public const int Restart = 0x03;
    }
}
